package com.oceanstar.service.Impl;

import com.oceanstar.Pojo.*;
import com.oceanstar.mapper.HealthMapper;
import com.oceanstar.mapper.UserInfoMapper;
import com.oceanstar.service.IHealthService;
import com.oceanstar.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class HealthServiceImpl implements IHealthService {
    // 注入mapper
    private final HealthMapper healthMapper;
    private final UserInfoMapper userInfoMapper;
    // 构造器注入
    public HealthServiceImpl(HealthMapper healthMapper, UserInfoMapper userInfoMapper) {
        this.healthMapper = healthMapper;
        this.userInfoMapper = userInfoMapper;
    }

    /*
     *上传健康数据
     */
    @Override
    public void updateHealthRecord(HealthInfo healthInfo, String token) throws Exception {
        Claims claims = JwtUtils.parseToken(token);
        Integer identity = (Integer) claims.get("identity");
        if (identity != 3) {
            throw new Exception("需为管理员权限");
        }
        // 检查该用户是否存在
        if (userInfoMapper.selectById(healthInfo.getId()) == null) {
            throw new Exception("该用户不存在");
        }
        healthInfo.setUpdateTime(new Date());
        healthMapper.insertHealthInfo(healthInfo);
    }

    /*
     *查询健康数据
     */
    @Override
    public <T> HealthHistoryDTO<T> getHealthHistory(Integer id, String metric, String token) throws Exception {
        Claims claims = JwtUtils.parseToken(token);
        Integer identity = (Integer) claims.get("identity");
        if(identity == 1 && id != claims.get("id")) {
            throw new Exception("老人只能查询自己的健康数据");
        }
        if (identity == 2 && id != claims.get("id")) {
            throw new Exception("家属只能查询关联老人的健康数据");
        }

        // 根据指标类型查询数据
        List<HealthInfo> healthInfos = healthMapper.selectHealthHistory(id);

        HealthHistoryDTO<T> dto = new HealthHistoryDTO<>();
        dto.setMetric(metric);

        // 按不同指标类型处理数据
        switch (metric) {
            case "heartRate":
                dto.setTimeline(healthInfos.stream()
                        .map(info -> formatDate(info.getUpdateTime()))
                        .collect(Collectors.toList()));
                dto.setValues((List<T>) healthInfos.stream()
                        .map(HealthInfo::getHeartRate)
                        .collect(Collectors.toList()));
                break;

            case "bloodPressure":
                dto.setTimeline(healthInfos.stream()
                        .map(info -> formatDate(info.getUpdateTime()))
                        .collect(Collectors.toList()));
                List<Integer> systolic = new ArrayList<>();
                List<Integer> diastolic = new ArrayList<>();
                for (HealthInfo info : healthInfos) {
                    String[] bp = info.getBloodPressure().split("/");
                    systolic.add(Integer.parseInt(bp[0]));
                    diastolic.add(Integer.parseInt(bp[1]));
                }
                dto.setSystolic(systolic);
                dto.setDiastolic(diastolic);
                break;

            case "bloodSugar":
                dto.setTimeline(healthInfos.stream()
                        .map(info -> formatDate(info.getUpdateTime()))
                        .collect(Collectors.toList()));
                dto.setValues((List<T>) healthInfos.stream()
                        .map(HealthInfo::getBloodSugar)
                        .collect(Collectors.toList()));
                break;

            case "weight":
                dto.setTimeline(healthInfos.stream()
                        .map(info -> formatDate(info.getUpdateTime()))
                        .collect(Collectors.toList()));
                dto.setValues((List<T>) healthInfos.stream()
                        .map(HealthInfo::getWeight)
                        .collect(Collectors.toList()));
                break;

            case "allergyHistory":
                // 收集所有过敏历史，对重复过敏只保留最早出现的记录，忽略"无"的记录
                Map<String, String> uniqueAllergies = new LinkedHashMap<>();
                healthInfos.stream()
                        .sorted(Comparator.comparing(HealthInfo::getUpdateTime))
                        .forEach(info -> {
                            if (info.getAllergyHistory() != null && !"无".equals(info.getAllergyHistory().trim())) {
                                Arrays.stream(info.getAllergyHistory().split(","))
                                        .map(String::trim)  // 去除前后空格
                                        .filter(allergy -> !allergy.isEmpty() && !"无".equals(allergy))
                                        .forEach(allergy -> {
                                            if (!uniqueAllergies.containsKey(allergy)) {
                                                uniqueAllergies.put(allergy, formatDate(info.getUpdateTime()));
                                            }
                                        });
                            }
                        });

                // 设置返回数据
                if (!uniqueAllergies.isEmpty()) {
                    dto.setAllergy(new ArrayList<>(uniqueAllergies.keySet()));
                    dto.setDiagnosisDate(new ArrayList<>(uniqueAllergies.values()));
                } else {
                    // 如果所有记录都是"无"，则返回空列表
                    dto.setAllergy(Collections.emptyList());
                    dto.setDiagnosisDate(Collections.emptyList());
                }

                dto.setLastUpdate(formatDateTime(healthInfos.stream()
                        .max(Comparator.comparing(HealthInfo::getUpdateTime))
                        .orElseThrow().getUpdateTime()));
                break;

            case "medicalHistory":
                // 收集所有疾病历史，对重复疾病只保留最早出现的记录
                Map<String, String> uniqueDiseases = new LinkedHashMap<>();
                healthInfos.stream()
                        .sorted(Comparator.comparing(HealthInfo::getUpdateTime))
                        .forEach(info -> {
                            if (info.getMedicalHistory() != null) {
                                Arrays.stream(info.getMedicalHistory().split(","))
                                        .filter(disease -> !disease.trim().isEmpty())
                                        .forEach(disease -> {
                                            if (!uniqueDiseases.containsKey(disease.trim())) {
                                                uniqueDiseases.put(disease.trim(), formatDate(info.getUpdateTime()));
                                            }
                                        });
                            }
                        });

                dto.setDisease(new ArrayList<>(uniqueDiseases.keySet()));
                dto.setDiagnosisDate(new ArrayList<>(uniqueDiseases.values()));
                dto.setLastUpdate(formatDateTime(healthInfos.stream()
                        .max(Comparator.comparing(HealthInfo::getUpdateTime))
                        .orElseThrow().getUpdateTime()));
                break;

            default:
                throw new Exception("不支持的指标类型");
        }

        return dto;
    }

    /*
     *标记或取消标记老人
     */
    @Override
    public void MarkElder(MarkMessage message, String token) throws Exception {
        // 检查该用户是否存在
        if (userInfoMapper.selectById(message.getElderlyId()) == null) {
            throw new Exception("该老人不存在");
        }
        if(message.getOperation() == 1){
            message.setLastUpdate(new Date());
            try {
                healthMapper.insertMarkElder(message);
            } catch (Exception e) {
                throw new Exception("插入失败：" + e.getMessage());
            }
        }
        else if(message.getOperation() == 0){
            healthMapper.deleteMarkElder(message);
        }
        else {
            throw new Exception("不支持的操作类型");
        }
    }

    /*
     *获取标记老人列表
     */
    @Override
    public PageInfo<MarkedElderDTO> getMarkedElderList(int page, int pageSize) {
        // 参数校验
        if (page < 1) {
            page = 1;
        }
        if (pageSize < 1) {
            pageSize = 10;
        }

        // 计算分页偏移量
        Integer offset = (page - 1) * pageSize;

        // 查询当前页数据
        List<MarkMessage> markMessageList = healthMapper.selectMarkedElderList(offset, pageSize);

        //转换为MarkedElderDTO对象列表
        List<MarkedElderDTO> markedElderList = markMessageList.stream().map(markMessage -> {
            MarkedElderDTO dto = new MarkedElderDTO();

            // 设置基本字段
            dto.setElderlyId(markMessage.getElderlyId());
            dto.setMarkReason(markMessage.getReason());
            dto.setLastUpdate(markMessage.getLastUpdate());

            // 查询老人详细信息
            UserInfo elderInfo = userInfoMapper.selectById(markMessage.getElderlyId());
            dto.setName(elderInfo.getName());

            //计算老人年龄
            String birthDateStr = elderInfo.getIdCard().substring(6, 14);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
            LocalDate birthDate = LocalDate.parse(birthDateStr, formatter);
            LocalDate currentDate = LocalDate.now();
            dto.setAge(Period.between(birthDate, currentDate).getYears());

            return dto;
        }).collect(Collectors.toList());

        // 查询总记录数
        long total = healthMapper.countMarkedElderList();
        // 构建并返回PageResult对象
        return new PageInfo<>(total, markedElderList);
    }

    private String formatDate(Date date) {
        return new SimpleDateFormat("yyyy-MM-dd").format(date);
    }
    private String formatDateTime(Date date) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }
}
